package com.logic.saas.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.logic.saas.enums.CountryEnum;
import com.logic.saas.enums.PricePeriodEnum;
import com.logic.saas.enums.PriceStrategyEnum;
import com.logic.saas.enums.PriceUnitEnum;
import com.logic.saas.enums.StateEnum;
import com.logic.saas.enums.SubscriptionPeriodEnum;
import com.logic.saas.enums.SubscritionStatusEnum;
import com.logic.saas.enums.UserStatusEnum;
import com.logic.saas.enums.UserTypeEnum;
import com.logic.saas.persistence.QcodeMapper;
import com.logic.saas.pojo.Kind;
import com.logic.saas.pojo.Ps;
import com.logic.saas.pojo.Qcode;
import com.logic.saas.util.AddLog;

@Service
public class EnumsService extends BaseService{
	
	private Logger logger = Logger.getLogger(EnumsService.class.getName());
	public EnumsService() {
		
	}
	@Autowired
	private QcodeMapper qcodeMapper;
	@Autowired
	private QcodeService qcodeService;
	/**
	 * update all enums to DB
	 * @return
	 * @throws Exception
	 */
	@Transactional
	public boolean updateAllEnums() throws Exception{
		AddLog.debug(EnumsService.class, "update enums begin");
		boolean synSuccess = false;
		List<Qcode> list = new ArrayList<Qcode>();
		//User Type
		loadUserTypeEnum(list);
		
		//
		loadUserStatusEnum(list);
		//
		loadPriceStrategyEnum(list);
		loadSubscritionStatusEnum(list);
		
		loadPricePeriodEnum(list);
		loadPriceUnitEnum(list);
		
		loadSubPeriodEnum(list);
		loadStateEnum(list);
		loadCountryEnum(list);
		
		synSuccess = synchronizeEnumsToDB(list);

		AddLog.debug(EnumsService.class, "update enums done!");
		return synSuccess;
	}
	

	@Transactional(readOnly=false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	private boolean synchronizeEnumsToDB(List<Qcode> codesList) throws Exception{
		boolean sysSuccess = false;
		//得到目前数据库中的所有Enums
		List<Qcode> dbCodes = qcodeMapper.queryQcode(new Ps());
		
		if(codesList != null){
			for(Qcode qcode : codesList){
				if(qcode != null){
					Map<String, Boolean> resultMap = this.checkQcodeChanges(dbCodes, qcode);
					if(resultMap.get("isConatin")){
						if(resultMap.get("isChanged")){
							//update
							logger.info("####operate UPDATE: "+qcode.getShortName() +" - "+ qcode.getFullName());
							qcodeService.updateQcode(qcode);
						}
					}else{
						//insert
						logger.info("####operate INSERT: "+qcode.getShortName() +" - "+ qcode.getFullName());
						qcodeService.insertQcode(qcode);
					}
				}
			}
		}
		if(dbCodes != null){
			for(Qcode qcode : dbCodes){
				if(qcode != null){
					Map<String, Boolean> resultMap = this.checkQcodeChanges(codesList, qcode);
					if(!resultMap.get("isConatin")){
						//delete	
						logger.info("####operate DELETE: "+qcode.getId()+"  --  "+qcode.getShortName() +" - "+ qcode.getFullName());
						qcodeService.deleteQcode(qcode.getId());
					}
				}
			}
		}
		sysSuccess = true;
		
		return sysSuccess;
			
	}
	
	/**
	 * 判断一个qcode list中是否包含qcode,并判断qcode是否有变化
	 * @param docList
	 * @param document
	 * @return
	 * @author jeffdong
	 */
	private Map<String, Boolean> checkQcodeChanges(List<Qcode> qcodeList, Qcode qcode){
		Map<String, Boolean> resultMap = new HashMap<String, Boolean>();
		boolean isContain = false;
		boolean isChanged = false;
		if(qcodeList != null && qcodeList.size() >0 && qcode != null){
			for(Qcode qcodeTemp : qcodeList){
				if(qcodeTemp != null && StringUtils.isNotBlank(qcodeTemp.getShortName()) && StringUtils.isNotBlank(qcode.getShortName())){
					//相等，肯定包含isContain = true
					if(qcodeTemp.getKind().getShortName().equals(qcode.getKind().getShortName()) && qcode.getShortName().equals(qcodeTemp.getShortName())){
						isContain = true;
						//查看是否有变化
						if(qcodeTemp.equals(qcode)){
							isChanged = false;
						}else{//有变化则把fullname改变
							qcode.setKind(qcodeTemp.getKind());
							qcode.setId(qcodeTemp.getId());
							isChanged = true;
						}
						break;
					}
				}
			}
		}
		resultMap.put("isConatin", isContain);
		resultMap.put("isChanged", isChanged);
		return resultMap;
	}
	
	/**
	 * 
	 * @param list
	 * @param shortName
	 * @param fullName
	 * @param kindName
	 */
	private void AddToEnumList(List<Qcode> list, String shortName,String fullName,Kind kind, Integer priority) {
		Qcode qcode = new Qcode();
		qcode.setShortName(shortName);
		qcode.setFullName(fullName);
		qcode.setKind(kind);
		qcode.setPriority(priority);
		list.add(qcode);
	}
	
	public void loadUserTypeEnum(List<Qcode> list){
		List<UserTypeEnum> dnum = Arrays.asList(UserTypeEnum.values());
		Iterator<UserTypeEnum> it = dnum.iterator();
		while(it.hasNext()){
			UserTypeEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	public void loadUserStatusEnum(List<Qcode> list){
		List<UserStatusEnum> dnum = Arrays.asList(UserStatusEnum.values());
		Iterator<UserStatusEnum> it = dnum.iterator();
		while(it.hasNext()){
			UserStatusEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	public void loadPriceStrategyEnum(List<Qcode> list){
		List<PriceStrategyEnum> dnum = Arrays.asList(PriceStrategyEnum.values());
		Iterator<PriceStrategyEnum> it = dnum.iterator();
		while(it.hasNext()){
			PriceStrategyEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	public void loadSubscritionStatusEnum(List<Qcode> list){
		List<SubscritionStatusEnum> dnum = Arrays.asList(SubscritionStatusEnum.values());
		Iterator<SubscritionStatusEnum> it = dnum.iterator();
		while(it.hasNext()){
			SubscritionStatusEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	public void loadPriceUnitEnum(List<Qcode> list){
		List<PriceUnitEnum> dnum = Arrays.asList(PriceUnitEnum.values());
		Iterator<PriceUnitEnum> it = dnum.iterator();
		while(it.hasNext()){
			PriceUnitEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	public void loadPricePeriodEnum(List<Qcode> list){
		List<PricePeriodEnum> dnum = Arrays.asList(PricePeriodEnum.values());
		Iterator<PricePeriodEnum> it = dnum.iterator();
		while(it.hasNext()){
			PricePeriodEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	
	public void loadSubPeriodEnum(List<Qcode> list){
		List<SubscriptionPeriodEnum> dnum = Arrays.asList(SubscriptionPeriodEnum.values());
		Iterator<SubscriptionPeriodEnum> it = dnum.iterator();
		while(it.hasNext()){
			SubscriptionPeriodEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	
	public void loadStateEnum(List<Qcode> list){
		List<StateEnum> dnum = Arrays.asList(StateEnum.values());
		Iterator<StateEnum> it = dnum.iterator();
		while(it.hasNext()){
			StateEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
	
	public void loadCountryEnum(List<Qcode> list){
		List<CountryEnum> dnum = Arrays.asList(CountryEnum.values());
		Iterator<CountryEnum> it = dnum.iterator();
		while(it.hasNext()){
			CountryEnum c = it.next();
			c.getKind().setId(null);
			AddToEnumList(list, c.getShortName(),c.getFullName(),c.getKind(),c.getPriority());
		}
	}
}
